
package ocbn.remotelab.GUI;
import ocbn.remotelab.events.FileStorage;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import ocbn.remotelab.util.GridFieldManager;
import java.util.Vector;
import ocbn.remotelab.events.*;
import javax.microedition.io.file.FileConnection.*;
import ocbn.remotelab.xml.*;
import net.rim.device.api.system.Display;
import net.rim.device.api.i18n.SimpleDateFormat;
import ocbn.remotelab.client.EventListener;




/**
 * This class retrieves past events from filestorage and display them as an
 * scrollable event table: <br>
 * <br>
 * ID: The ID of the event. <br>
 * Time: The time the event occurred. <br>
 * Source: The source of the equipment that generated the event. <br>
 * State: The state of the event. <br>
 * Detail: Opens up a new screen for the user to see the detail of each event. <br>
 *
 * @author Ke
 */
public class MSTableScreen extends MainScreen implements EventListener{


    //Create managers to display table.
    private VerticalFieldManager Back;
    private GridFieldManager middle;

    //Vector of events where the table data is extracted from.
    private Vector vecEvents;

    //variable storing an incoming new event.
    private Event newEvent;

    /**
     * Constructor for the class, creates a table displaying all the events.
     */
    public MSTableScreen() {
        super();

        LabelField title = new LabelField("Event Table(Mock Data)"
                , LabelField.USE_ALL_WIDTH);
        setTitle(title);
        Back = new VerticalFieldManager(Manager.HORIZONTAL_SCROLL);
        add(Back);

       

        //Set the font size
        Font font_bold_16 = this.getFont().derive(Font.BOLD, 16);
        this.setFont(font_bold_16);

        
        //obtain pastEvents. TODO: finish this for PhaseIII.
        getEvents();

        //draw.
        drawTable();


    }

    /**
     * Draws the event table by adding each element in the appropriate fasion
     * to the GridFieldManager.
     */
    private void drawTable() {
        //Create a Gridmanager that will lay out the table.
        int width = Display.getWidth();
        int[] columnWidth = {20, width * 2 / 5 - 30
                ,  width/6,  width/4,  width/5};
        middle = new GridFieldManager(columnWidth, Manager.HORIZONTAL_SCROLL);
        Back.add(middle);

        //Draw table header.
        middle.add(new LabelField("ID"));
        middle.add(new LabelField("Time"));
        middle.add(new LabelField("Source"));
        middle.add(new LabelField("State"));
        middle.add(new LabelField("Detail"));

         //add the events to the table
        for (int i = 0; i != vecEvents.size(); i++) {
            Event e = (Event) vecEvents.elementAt(i);
            drawEvents(e, i);

        }
    }

    /**
     * Add a single event to the GUI table.
     * @param e The event to be added.
     * @param i The number of the event.
     */
    private void drawEvents(Event e, int i) {
                    if (e.getType() == MassSpectrometerStateEvent.class) {

                MassSpectrometerStateEvent me = (MassSpectrometerStateEvent) e;

                middle.add(new LabelField("" + me.getID()));
                middle.add(new LabelField(""
                        + new SimpleDateFormat("MMM d hh:mm aa").format(
                        me.getTime())));
                middle.add(new LabelField(me.getSource()));
                middle.add(new LabelField(""
                        + me.getState().name().toLowerCase()));

                //Create a button field for each event.
                ButtonField detail = new ButtonField("Detail"
                        , ButtonField.CONSUME_CLICK );
                middle.add(detail);
                //Create a listener and add it to this button
                detail.setChangeListener(new MSButtonListener(i));
            }
    }

    /**
     * Obtains the MS events by accessing filestorage.
     */
    private void getEvents() {

           vecEvents = FileStorage.loadMSEvents();
    }

    /**
     * Automatically called by PacketProcessor when Event arrived.
     * This method adds the newly arrived packet to GUI table for display.
     * @param e The newly arrived Event.
     */
    public void EventReceived(Event e) {
            newEvent = e;
           //Repaintthe GUI table
           UiApplication.getUiApplication().invokeLater(new Runnable() {

            public void run() {
                //add the incoming event to the vector of events
                vecEvents.addElement(newEvent);
                //add this Event to the displaying GUI.
                drawEvents(newEvent,vecEvents.indexOf(newEvent));
            }
        });

    }

    /**
     * A class that listens to when the button corrosponding to a specific
     * event is clicked. It then launches the appropriate detail screen.
     */
    private class MSButtonListener implements FieldChangeListener{
          private int eventIndex;

          /**
           * Create a new  listener
           * @param index the index of the event that the button corrosponds to.
           */
          private MSButtonListener(int index){
              eventIndex = index;
          }

          /**
           * Evoked when the button is clicked
           * @param field the field that's changed
           * @param context the context of that field
           */
          public void fieldChanged(Field field, int context) {


           //get the event that the button corrospond to.
           MassSpectrometerStateEvent e =
                   (MassSpectrometerStateEvent) vecEvents.elementAt(eventIndex);

              //push detail screen.
              MSDetailScreen ms = new MSDetailScreen();
              ms.setEventID(e.getID());
              ms.setDetailMessage(e.getDetails());
              UiApplication.getUiApplication().pushScreen(ms);

            }
    }

     /**
     * Make a menu and define menu item properties.
      * @param menu the screen's menu
      * @param instance  menu's instance
      */
    protected void makeMenu(Menu menu, int instance) {
          menu.add(delete);
          menu.add(close);
    }

    //A menu item that lets the user to clear the entire list
    private MenuItem delete = new MenuItem("Clear List", 110, 10) {

        public void run() {

           //Clear the MS event by deleting them from the file
           FileStorage.clearMSEvent();
           vecEvents.removeAllElements();

           //Repaint the GUI table
           UiApplication.getUiApplication().invokeLater(new Runnable() {

            public void run() {
                 //Delete the current table.
                Back.delete(middle);

                //get new events.
                getEvents();
                //redraw table.
                drawTable();
            }
        });


        }
    };

    //MenuItem that closes the screen
    private MenuItem close = new MenuItem("Close", 110, 10) {

        public void run() {

            onClose();
        }
    };


    /**
     * Overiding the parent method to avoid save Prompt().
     * @return always returns true
     */
    protected boolean onSavePrompt(){
        return true;
    }

}


